home *** CD-ROM | disk | FTP | other *** search
/ Mac Expert 1995 Winter / Mac Expert - Winter 95.iso / Les fichiers / Communications / Internet / TurboTCP 2.1 ƒ / TurboTCP core / CTelnetInterp.cp < prev    next >
Encoding:
Text File  |  1995-01-06  |  7.8 KB  |  372 lines  |  [TEXT/MMCC]

  1. //
  2. // CTelnetInterp.cp
  3. //
  4. //    TurboTCP library
  5. //    Generic Telnet protocol interpreter
  6. //
  7. //    Copyright © 1993-95, FrostByte Design / Eric Scouten
  8. //
  9.  
  10. #include "CTelnetInterp.h"
  11.  
  12. #if TurboTCP_TCL
  13.     TCL_DEFINE_CLASS_M1(CTelnetInterp, CTCPEndpoint);
  14. #endif
  15.  
  16.  
  17. //***********************************************************
  18.  
  19. CTelnetInterp::CTelnetInterp
  20.     (unsigned short    theDefaultPort,            // default IP port number (the only required parameter)
  21.     unsigned long        recBufferSize,            // size of receive buffer to create
  22.     unsigned short    autoReceiveSize,        // number of entries in RDS for auto receive
  23.     unsigned short    autoReceiveNum,        // number of auto-receive calls to issue at once
  24.     Boolean            doUseCName)            // true to get canonical name of remote host
  25.                                         //    whenever possible
  26.  
  27. : CTCPEndpoint(theDefaultPort, recBufferSize, autoReceiveSize, autoReceiveNum, doUseCName)
  28.  
  29. {
  30.     itsState = normalChar;
  31.     showFileName = false;
  32. }
  33.  
  34.  
  35. //***********************************************************
  36. //
  37. // Telnet command handling methods
  38. //
  39. //    If you wish to respond to specific Telnet commands, override these methods.
  40. //    You may ignore any or all of these methods.
  41. //
  42.  
  43. //***********************************************************
  44.  
  45. void CTelnetInterp::ReceivedWill        // protected method
  46.     (uchar theOption)                // the option number
  47.  
  48.     // Respond to a Telnet [IAC WILL option] sequence. Default method responds [WONT option].
  49.     // Override to implement any Telnet options, call this method to reject any unimplemented
  50.     // options.
  51.  
  52.  
  53. {
  54.     char respondStr[4];
  55.  
  56.  
  57.     // reject all options
  58.  
  59.     respondStr[0] = charIAC;
  60.     respondStr[1] = escWONT;
  61.     respondStr[2] = theOption;
  62.     respondStr[3] = '\0';
  63.     if (showDebug) {
  64.         PrintDebugStr("{IAC WONT");
  65.         PrintDebugCharNum(theOption, ' ', '}');
  66.     }
  67.     *this << respondStr;
  68. }
  69.  
  70.  
  71. //***********************************************************
  72.  
  73. void CTelnetInterp::ReceivedDo        // protected method
  74.     (uchar theOption)                // the option number
  75.  
  76.     // Respond to a Telnet [IAC DO option] sequence. Default method responds [WONT option].
  77.     // Override to implement any Telnet options, call this method to reject any unimplemented
  78.     // options.
  79.  
  80. {
  81.     char respondStr[4];
  82.  
  83.  
  84.     // reject all options
  85.     
  86.     respondStr[0] = charIAC;
  87.     respondStr[1] = escWONT;
  88.     respondStr[2] = theOption;
  89.     respondStr[3] = '\0';
  90.     if (showDebug) {
  91.         PrintDebugStr("{IAC WONT");
  92.         PrintDebugCharNum(theOption, ' ', '}');
  93.     }
  94.     *this << respondStr;
  95. }
  96.  
  97.  
  98. //***********************************************************
  99.  
  100. void CTelnetInterp::ReceivedSB        // protected method
  101.     (uchar theChar)                    // the latest character
  102.  
  103. // Receive subnegotiation parameters. Buffers characters until SE is received.
  104.  
  105. {
  106.     if (showDebug)
  107.         PrintDebugCharNum(theChar, ' ', '\0');
  108.     sbBfr[sbBfrIndex++] = theChar;
  109. }
  110.  
  111.  
  112. // -- respond to incoming data (do not override) --
  113.  
  114. //***********************************************************
  115.  
  116. void CTelnetInterp::HandleDataArrived            // private method — DO NOT OVERRIDE!
  117.     (void*            theData,                // pointer to block of data
  118.     unsigned short    theDataSize,            // size of data block
  119.     Boolean            isUrgent)                // true if urgent data
  120.  
  121.     // Process incoming data. This is the guts of the Telnet interpreter.
  122.     // Your subclass must not override this method. You must instead override
  123.     // HandleNVTChar and HandleNVTLine to process data intended for the
  124.     // “terminal” that you are implementing.
  125.  
  126. {
  127.     char*    xData = (char*) theData;                // hack to avoid lots of typecasts
  128.     uchar    theChar;
  129.     char        theLine[83];
  130.     short    lineIndex;
  131.  
  132.  
  133.     // parse each character separately
  134.     
  135.     while (theDataSize--) {
  136.         theChar = (uchar) (*(xData++));
  137.  
  138.  
  139.         // respond to current Telnet state
  140.         
  141.         switch (itsState) {
  142.  
  143.  
  144.             // normal operation: write character
  145.             
  146.             case normalChar:
  147.  
  148.  
  149.                 // optimization: try to grab several chars at once
  150.                 
  151.                 lineIndex = 0;
  152.                 while ((theDataSize > 1) && (theChar >= ' ') && (theChar != charIAC)) {
  153.                     theDataSize++;
  154.                     xData--;
  155.                     lineIndex = 0;
  156.                     while ((theDataSize > 0) && (((uchar) *xData) >= ' ') &&
  157.                                             (*xData != charIAC) && (lineIndex < 80))
  158.                         theDataSize--, theLine[lineIndex++] = (uchar) *(xData++);
  159.                     if ((theDataSize > 0) && (*xData == charCR))
  160.                         theDataSize--, xData++, theLine[lineIndex++] = charCR;
  161.                     if ((theDataSize > 0) && (*xData == charLF))
  162.                         theDataSize--, xData++, theLine[lineIndex++] = charLF;
  163.                     theLine[lineIndex] = '\0';
  164.                     if (lineIndex)
  165.                         HandleNVTLine((char*) &theLine[0]);
  166.                     if (theDataSize < 1)
  167.                         break;
  168.                     theChar = (uchar) (*(xData++));
  169.                     theDataSize--;
  170.                 }
  171.                 
  172.                 if ((lineIndex) && !(theDataSize))
  173.                     break;
  174.  
  175.  
  176.                 // end of loop: test for IAC
  177.                 
  178.                 if (theChar == charIAC) {
  179.                     itsState = gotIAC;
  180.                     if (showDebug)
  181.                         PrintDebugStr("[IAC");
  182.                 }
  183.                 else
  184.                     HandleNVTChar(theChar);
  185.                 break;
  186.  
  187.  
  188.             // received IAC (interpret as command)
  189.             
  190.             case gotIAC:
  191.             case gotIACinSB:
  192.                 ReceivedIAC(theChar);
  193.                 break;
  194.  
  195.  
  196.             // handle other cases
  197.                 
  198.             case gotSB:
  199.                 if (theChar == charIAC) {
  200.                     itsState = gotIACinSB;
  201.                     if (showDebug)
  202.                         PrintDebugStr(" IAC");
  203.                 }
  204.                 else
  205.                     ReceivedSB(theChar);
  206.                 break;
  207.  
  208.             case gotWILL:
  209.                 if (showDebug)
  210.                     PrintDebugCharNum(theChar, ' ', ']');
  211.                 ReceivedWill(theChar);
  212.                 itsState = normalChar;
  213.                 break;
  214.  
  215.             case gotWONT:
  216.                 if (showDebug)
  217.                     PrintDebugCharNum(theChar, ' ', ']');
  218.                 ReceivedWont(theChar);
  219.                 itsState = normalChar;
  220.                 break;
  221.  
  222.             case gotDO:
  223.                 if (showDebug)
  224.                     PrintDebugCharNum(theChar, ' ', ']');
  225.                 ReceivedDo(theChar);
  226.                 itsState = normalChar;
  227.                 break;
  228.  
  229.             case gotDONT:
  230.                 if (showDebug)
  231.                     PrintDebugCharNum(theChar, ' ', ']');
  232.                 ReceivedDont(theChar);
  233.                 itsState = normalChar;
  234.                 break;
  235.         }
  236.     }
  237.  
  238. }
  239.  
  240.  
  241. //***********************************************************
  242.  
  243. void CTelnetInterp::ReceivedIAC            // private method
  244.     (uchar theCommand)                    // the command number
  245.  
  246.     // Respond to a Telnet [IAC command] sequence.
  247.     // As with HandleDataArrived, this method should not be overriden.
  248.  
  249. {
  250.  
  251.     // which command is it?
  252.  
  253.     switch (theCommand) {
  254.  
  255.         case escSE:
  256.             if (showDebug)
  257.                 PrintDebugStr(" SE]");
  258.             sbBfr[sbBfrIndex] = '\0';
  259.             if (itsState == gotIACinSB)
  260.                 ReceivedSE();
  261.             itsState = normalChar;
  262.             break;
  263.  
  264.         case escNOP:
  265.             if (showDebug)
  266.                 PrintDebugStr(" NOP]");
  267.             itsState = normalChar;
  268.             break;
  269.             
  270.         case escDM:
  271.             if (showDebug)
  272.                 PrintDebugStr(" DM]");
  273.             ReceivedSynch();
  274.             itsState = normalChar;
  275.             break;
  276.             
  277.         case escBRK:
  278.             if (showDebug)
  279.                 PrintDebugStr(" BRK]");
  280.             ReceivedBRK();
  281.             itsState = normalChar;
  282.             break;
  283.             
  284.         case escIP:
  285.             if (showDebug)
  286.                 PrintDebugStr(" IP]");
  287.             ReceivedIP();
  288.             itsState = normalChar;
  289.             break;
  290.             
  291.         case escAO:
  292.             if (showDebug)
  293.                 PrintDebugStr(" AO]");
  294.             ReceivedAO();
  295.             itsState = normalChar;
  296.             break;
  297.             
  298.         case escAYT:
  299.             if (showDebug)
  300.                 PrintDebugStr(" AYT]");
  301.             ReceivedAYT();
  302.             itsState = normalChar;
  303.             break;
  304.             
  305.         case escEC:
  306.             if (showDebug)
  307.                 PrintDebugStr(" EC]");
  308.             ReceivedEC();
  309.             itsState = normalChar;
  310.             break;
  311.             
  312.         case escEL:
  313.             if (showDebug)
  314.                 PrintDebugStr(" EL]");
  315.             ReceivedEL();
  316.             itsState = normalChar;
  317.             break;
  318.             
  319.         case escGA:
  320.             if (showDebug)
  321.                 PrintDebugStr(" GA]");
  322.             ReceivedGA();
  323.             itsState = normalChar;
  324.             break;
  325.             
  326.         case escSB:
  327.             if (showDebug)
  328.                 PrintDebugStr(" SB");
  329.             itsState = gotSB;
  330.             sbBfrIndex = 0;
  331.             break;
  332.         
  333.         case escWILL:
  334.             if (showDebug)
  335.                 PrintDebugStr(" WILL");
  336.             itsState = gotWILL;
  337.             break;
  338.             
  339.         case escWONT:
  340.             if (showDebug)
  341.                 PrintDebugStr(" WONT");
  342.             itsState = gotWONT;
  343.             break;
  344.         
  345.         case escDO:
  346.             if (showDebug)
  347.                 PrintDebugStr(" DO");
  348.             itsState = gotDO;
  349.             break;
  350.         
  351.         case escDONT:
  352.             if (showDebug)
  353.                 PrintDebugStr(" DONT");
  354.             itsState = gotDONT;
  355.             break;
  356.         
  357.         case escIAC:
  358.         default:
  359.             if (itsState == gotIACinSB) {
  360.                 ReceivedSB(theCommand);
  361.                 itsState = gotIAC;
  362.             }
  363.             else {
  364.                 if (showDebug)
  365.                     PrintDebugCharNum(theCommand, '?', ']');
  366.                 HandleNVTChar(theCommand);
  367.                 itsState = normalChar;
  368.             }
  369.     }
  370.  
  371. }
  372.